using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using nTools.PrefabPainter;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.Serialization;
using XYRendering.Vegetation;


namespace XYTerrain.Editor{


public class PrefabPainterSplit : EditorWindow
{

    public List<Transform> grassRoots;
    public bool drawBounds;
    public bool drawWaitToBeak;
    public bool combineAnRemove;
    
    public List<Terrain> terrains;
    public List<XYRendering.Vegetation.VGInstancingDataRenderer> instanceRenderers;
    
    private SerializedObject _serObj;
    private SerializedProperty _terrainpty;
    private SerializedProperty _grassRootpty;

    private PrefabPainter _painter;
    private PrefabPainterDataBakerGUI _beakGUI;

    #region  GUIContex

    private GUIContent beginSplitbtn = new GUIContent("开始分批");
    

    #endregion
    
    
    
    /// <summary>
    /// Root中的提取方案
    /// </summary>
    public enum SelectMode
    {
        SingleGroup,
        MultiGroup
    }


    [MenuItem("Tools/Nature Manufacture/XY/Terrain草分块处理工具")]
    public static void OpenWindow()
    {
        var windows = EditorWindow.GetWindow<PrefabPainterSplit>("Terrain草分块处理工具");
    }
    

    public void OnGUI()
    {
       MainGUI(); 
    }


    public void OnEnable()
    {
        SceneView.duringSceneGui  += OnSceneGUI;
        _serObj = new SerializedObject(this);
        _terrainpty = _serObj.FindProperty("terrains");
        _grassRootpty = _serObj.FindProperty("grassRoots");
        _instanceRenderers_Prop = _serObj.FindProperty("instanceRenderers");
        _waitToBeak_Prop = _serObj.FindProperty("waitToBeak");
    }

    public void OnDisable()
    {
        SceneView.duringSceneGui -= OnSceneGUI;
    }
    

    

    public void OnSceneGUI(SceneView sceneView)
    {
        if(drawBounds) DrawTerrainsBounds();
        if (drawWaitToBeak) DrawWaitToBeakBox();
    }


    void DrawScrollerList(ref Vector2 scroller,SerializedProperty property)
    {
        if (property.isExpanded) 
        {
            using (var scrollView = new EditorGUILayout.ScrollViewScope(scroller, GUILayout.Height((200)),GUILayout.Width(250)))
            {
                 scroller = scrollView.scrollPosition;
                 EditorGUILayout.PropertyField(property);
            }
        }
        else
        {
           EditorGUILayout.PropertyField(property);
        }
    }


    #region 获取待烘焙地形

    public List<Terrain> waitToBeak;
    private SerializedProperty _waitToBeak_Prop;
    private Vector2 _waitToBeak_Scroller;
    private bool _waitToBeak_Show;
    public static string dataSavePath = null;

    private string GetSavePath()
    {
        return EditorUtility.SaveFolderPanel("保存路径","Assets","");
    }
    
    private void DrawWaitToBeak()
    {
       EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
       
       DrawScrollerList(ref _waitToBeak_Scroller,_waitToBeak_Prop);

       
        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
        
        //=== 显示配置路径 ===
        
        
        EditorGUILayout.LabelField(dataSavePath,EditorStyles.helpBox);
        if (GUILayout.Button("打开路径配置"))
        {
            dataSavePath = GetSavePath();
        }
        EditorGUILayout.Space(5);
                       
                       
                       
                       
       //=================
        
        if (GUILayout.Button("获取所有待烘焙地形"))
        {
            GetAllWaitToBeak();
        }
        
        

        if (GUILayout.Button("烘焙选中地形"))
        {
            var o = Selection.activeGameObject;
            BeakSelectionTerrain(o);
        }

        if (GUILayout.Button("烘焙所有地形"))
        {
            BeakAllGrassData();    
        }
        
        EditorGUILayout.EndVertical();
       
       EditorGUILayout.EndHorizontal();
        
    }


    private  void GetBeakWindow()
    {
        if(_beakGUI != null) return;
        _painter = EditorWindow.GetWindow<PrefabPainter>();
        foreach (var i in _painter._editorExtendsions)
        {
            if (i.GetType() == typeof(PrefabPainterDataBakerGUI) )
            {
                _beakGUI = i as PrefabPainterDataBakerGUI;
            }
        }
    }
    
    /// <summary>
    /// 自己用 先定死固定路径
    /// </summary>
    // public string DataPath = "Assets/Art/Scene/TerrainSplit/GrassData/Scene1";
    
    private void BeakSelectionTerrain(GameObject o)
    {
        GetBeakWindow();


        dataSavePath ??= GetSavePath(); 
        var savePath = dataSavePath.Substring(Application.dataPath.Length-6);
        
        
        
        var list = AssetDatabase.FindAssets("t:VGInstancingData", new[] {savePath});
        VGInstancingData newData = null;
        foreach (var i in list)
        {
           string n   = (AssetDatabase.GUIDToAssetPath(i));
           var sp = n.Split('/');
           var name = sp[sp.Length - 1];
           
           if (name.Contains(o.name))
           {
               Debug.Log("存在已有数据");
               newData = AssetDatabase.LoadAssetAtPath<VGInstancingData>(n);
               break;
           }
        }

        if (newData == null)
        {
            Debug.Log( $"未存在数据 将会在{savePath}目录下生成");
            newData = ScriptableObject.CreateInstance<VGInstancingData>();
            newData.name = o.name+"_GrassData"; 
            AssetDatabase.CreateAsset(newData,savePath+"/"+newData.name+".asset");
            // AssetDatabase.SaveAssets();
           
        }
           
        
        _beakGUI._bakeSetting.placingGO = o;
        _beakGUI._bakeSetting.data = newData;
        
        _painter.SetCurrentTag((PrefabPainter.PaintTool)9);
        // EditorUtility.SetDirty(painter);
        _painter.Repaint();







    }


    private void BeakAllGrassData()
    {

        List<Terrain> hasCreat = new List<Terrain>();

        for (int i = 0; i < waitToBeak.Count; i++)
        {
            BeakSelectionTerrain(waitToBeak[i].gameObject);
            int errorNum = 0;
            _beakGUI.ExternalUseBeak(out errorNum);
            if (errorNum == 0)
            {
                hasCreat.Add(waitToBeak[i]);
            }
            else
            {
                Debug.LogWarning(waitToBeak[i].name+ "未能正确生成 请手动检查");
            }
            EditorUtility.DisplayProgressBar("生成中","烘焙中...."+i+"/"+waitToBeak.Count,i/(float)waitToBeak.Count);
        }
        EditorUtility.ClearProgressBar();
        

        foreach (var i in hasCreat)
        {
            waitToBeak.Remove(i);
        }
        hasCreat.Clear();
        
        
            
        
        

    }
    
    
    
    
    
    void GetAllWaitToBeak()
    {
        GetAllTerrain();
        waitToBeak = new List<Terrain>();
        foreach (var i in terrains)
        {
            foreach (Transform t in i.transform)
            {
                if (t.name.Contains("_group"))
                {
                    Debug.Log("get1");
                    waitToBeak.Add(i);
                    break;
                    
                }
            }
        }
        
        
    }
    
    

    #endregion
    
    #region 收集并处理当前场景中存在草的分块
    

    private SerializedProperty _instanceRenderers_Prop;
    private Vector2 _instanceRenders_Scroller;
    private bool _overriderShow;

    public OverriderInt lodCount = new OverriderInt(3);
    public OverriderInt maxDistance = new OverriderInt(100);
    public OverriderInt lod1Distance = new OverriderInt(30);
    public OverriderInt lod2Distance= new OverriderInt(50);
    public OverriderInt lod3Distance = new OverriderInt(100);
    public OverriderFloatRange heightOffset = new OverriderFloatRange(0f, -10f, 10f);
     
    
    
    
    void DrawCollectionGUI()
    {

        
            //已经生成物体收集
            EditorGUILayout.BeginHorizontal(EditorStyles.helpBox,GUILayout.Width(300));
            // _ins_render_Show = EditorGUILayout.Foldout( _ins_render_Show,"已经收集场景物体");
            DrawScrollerList(ref _instanceRenders_Scroller,_instanceRenderers_Prop); 
            EditorGUILayout.BeginVertical();
            
            if (GUILayout.Button("获取场景中所有已烘焙草"))
            {
                GetHasBreak(); 
            }

            if (GUILayout.Button("TODO统一还原"))
            {
                
            }


            _overriderShow = EditorGUILayout.Foldout(_overriderShow, "覆写数值");
            if (_overriderShow)
            {
                
                DrawOverriderInstanceValue();
                if (GUILayout.Button("覆盖数值"))
                {
                    foreach (var i in instanceRenderers)
                    {
                        Vector4 lodValue = new Vector4();
                        lodValue.x = lod1Distance.overrider ? lod1Distance.value : i.lodDistances.x;
                        lodValue.y = lod2Distance.overrider ? lod2Distance.value : i.lodDistances.y;
                        lodValue.z = lod3Distance.overrider ? lod3Distance.value : i.lodDistances.z;
                        lodValue.w = 100;
                        i.lodDistances = lodValue;
                        i.lodCount = 3;
                        // i.lodCount = 3;
                        i.maxLodDistance = maxDistance.overrider ? maxDistance.value : i.maxLodDistance;
                        i.Refresh();
                        EditorUtility.SetDirty(i);
                        // i.lodDistances = new Vector4(30, 60, 100, 100);
                    }
                    Debug.Log("完成");
                }
            }

            if (GUILayout.Button("移除所有草绘制组件"))
            {
                foreach (var i in instanceRenderers)
                {
                    EditorUtility.SetDirty(i.gameObject);
                    if(i!=null) GameObject.DestroyImmediate(i); 
                } 
                instanceRenderers.Clear();
                
            }
            


            if (GUILayout.Button("SwitchState"))
            {
                foreach (var i in instanceRenderers)
                {
                    i.enabled = !i.enabled;
                    EditorUtility.SetDirty(i);
                }
            }
            
            EditorGUILayout.EndVertical();
            EditorGUILayout.EndHorizontal();     
        
    }

    public void DrawOverriderInstanceValue()
    {


        EditorGUILayout.BeginVertical(EditorStyles.helpBox);

        
        
        maxDistance.DrawEditorIns("MaxDistance");
        lod1Distance.DrawEditorIns("Lod1");
        lod2Distance.DrawEditorIns("Lod2");
        lod3Distance.DrawEditorIns("Lod3");
        heightOffset.DrawEditorIns("HeightOffset");
        EditorGUILayout.EndVertical();
       

    }
    
    
    
    
    
    
     
    void GetHasBreak()
    {
        var list = FindObjectsOfType<XYRendering.Vegetation.VGInstancingDataRenderer>();
        Debug.Log(list.Length);
        instanceRenderers = new List<VGInstancingDataRenderer>();
        foreach (var i in list)
        {
           instanceRenderers.Add(i); 
        }
    }

    void CheckTerrainGrass()
    {
        
    }
    
    

    #endregion

    
    
    

    #region 刷草基于地形分块以及合并功能

    
    private Vector2 terrainsScrollPos;
    private Vector2 grassRootScrollPos;
    private void MainGUI()
    {


        
        EditorGUILayout.Space(10);
        
        
        EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
        DrawTerrainCollection(); 
        EditorGUILayout.Space(20);
        DrawGrassRootCollection(); 
        EditorGUILayout.EndHorizontal(); 
        
        EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
        DrawCollectionGUI();
        EditorGUILayout.Space(20);
        DrawWaitToBeak();
        EditorGUILayout.EndHorizontal(); 
        
        DrawFunction();
        UpdateSerializedObject();
        
        DrawDebugData();
        
        

    
        
        
        
        
    }

    private void UpdateSerializedObject()
    {
        _serObj.Update();
        EditorGUI.BeginChangeCheck();
        if (EditorGUI.EndChangeCheck())
        {
            _serObj.ApplyModifiedProperties();
        }
    }


    private void DrawTerrainCollection()
    {
         if (_terrainpty != null)
         {

             
             EditorGUILayout.BeginVertical();
             EditorGUILayout.LabelField("地形列表");
             EditorGUILayout.BeginHorizontal(EditorStyles.helpBox,GUILayout.Width(300));
             if (_terrainpty.isExpanded)
             {
                using (var scrollView = new EditorGUILayout.ScrollViewScope(terrainsScrollPos, GUILayout.Height((200)),GUILayout.Width(250)))
                {
                    terrainsScrollPos = scrollView.scrollPosition;
                    EditorGUILayout.PropertyField(_terrainpty);
                }
             }
             else
             {
                EditorGUILayout.PropertyField(_terrainpty);
             }

             EditorGUILayout.BeginVertical();
             
             combineAnRemove = EditorGUILayout.Toggle("还原后移除",combineAnRemove);
             
             if (GUILayout.Button(new GUIContent("获取全部地形","获取全部激活地形") ))
                GetAllTerrain();
             
             if (GUILayout.Button("清除全部地形"))
                 terrains.Clear();
             
             if (GUILayout.Button("从地形中还原植被"))
             {
                 var list = new List<GameObject>();
                 foreach (var i in terrains)
                 {
                    list.Add(i.gameObject); 
                 }
                 CombineAllGrass(list); 
             }
             EditorGUILayout.EndVertical();
             
             EditorGUILayout.Space(3);
             EditorGUILayout.EndHorizontal();
             EditorGUILayout.EndVertical();
             
         }   
    }



    public void DrawFunction()
    {
        EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
        
        if (terrains!=null && terrains.Count > 0)
        {
            drawBounds = EditorGUILayout.Toggle("Debug地形碰撞盒",drawBounds);
        }

        if (waitToBeak != null && waitToBeak.Count > 0)
        {
            
            drawWaitToBeak = EditorGUILayout.Toggle("Debug待生成碰撞盒",drawWaitToBeak);
        }
        
        EditorGUILayout.EndHorizontal();
    }


    private void ShowFinish()
    {
        EditorUtility.DisplayDialog("提示", "完成","ok");
    }

    public SelectMode mode;
    private void DrawGrassRootCollection()
    {
        if (_grassRootpty != null)
        {
            
            
            EditorGUILayout.BeginVertical();
            EditorGUILayout.LabelField("绘制草对象列表");
            EditorGUILayout.BeginHorizontal(EditorStyles.helpBox, GUILayout.Width(200));
            
            EditorGUILayout.BeginVertical();
            mode = (SelectMode)EditorGUILayout.EnumPopup("根节点传入模式",mode);
            
            if (_grassRootpty.isExpanded)
            {
                using (var scrollView = new EditorGUILayout.ScrollViewScope(grassRootScrollPos, GUILayout.Height((200)),GUILayout.Width(250)))
                {
                    grassRootScrollPos = scrollView.scrollPosition;
                    EditorGUILayout.PropertyField(_grassRootpty);
                }
            }
            else
            {
                EditorGUILayout.PropertyField(_grassRootpty);
            }
            EditorGUILayout.EndVertical();
            
            EditorGUILayout.BeginVertical();
            if (GUILayout.Button("清空列表"))
            {
                grassRoots.Clear();    
            }
            if (GUILayout.Button(beginSplitbtn))
            {
                if (mode == SelectMode.SingleGroup)
                {
                    foreach (var i in grassRoots) 
                               SplitTerrain(terrains,i);    
                }
                else
                {
                    foreach (var t in grassRoots)
                    {
                        foreach (Transform i in t)
                        {
                           SplitTerrain(terrains,i); 
                        } 
                    }
                }
                
                ShowFinish();
            }
            
            EditorGUILayout.EndVertical();
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();
        }
        
        
         
            
        
    }
    
    /// <summary>
    ///  所有Terrain下的子物体合并到一个父节点种
    /// </summary>
    public void CombineAllGrass(List<GameObject> terrainList)
    {
        // 用于存储每类草的绘制根节点
        Dictionary<string, List<Transform>> GrassDic= new Dictionary<string, List<Transform>>();

        foreach (var i in terrainList)
        {

            foreach (Transform childObject in i.transform)
            {
                
                var splitName = childObject.name.Split('_');
                var lastWord = splitName[splitName.Length - 1];
                if (lastWord == "group")
                {
                    if (!GrassDic.ContainsKey(childObject.name))
                    {
                        GrassDic.Add(childObject.name,new List<Transform>());    
                    }
                    GrassDic[childObject.name].Add(childObject);
                }    
            }
        }    
        
        //  收集完毕 准备创建
        var rootObjetList  = EditorSceneManager.GetActiveScene().GetRootGameObjects();

        Dictionary<string, GameObject> PrefabTable = WarmUpPrefab(GrassDic);


        foreach (var i in GrassDic)
        {

            GameObject o = GetNameInArray(rootObjetList, i.Key);
            if (o ==null) o = new GameObject(i.Key);
            o.transform.position = Vector3.zero;
            o.transform.rotation = Quaternion.identity;
            o.transform.localScale =  Vector3.one;
            
            
            foreach (Transform objRoot in i.Value )
            {
                foreach (Transform perObj in objRoot)
                {
                    GameObject g = null;
                    if (PrefabTable.ContainsKey(i.Key))
                    {
                       g =  PrefabUtility.InstantiatePrefab(PrefabTable[i.Key],o.transform) as GameObject;
                    }
                    else
                    {
                        g = GameObject.Instantiate(perObj.gameObject);
                    }
                    g.transform.position = perObj.transform.position;
                    g.transform.rotation = perObj.transform.rotation;
                    g.transform.localScale = perObj.transform.localScale;
                    // Undo.RegisterCreatedObjectUndo(o,"split_Creat_UnDo"); 
                } 
            }
        }
        
    
        
        //  移除原有草
        if (combineAnRemove) 
        {
            foreach (var i in GrassDic)
            {
                foreach (var roots in i.Value)
                {
                   GameObject.DestroyImmediate(roots.gameObject); 
                }
            }    
        }
        ShowFinish();

            
        
    }


    /// <summary>
    ///  
    /// </summary>
    public void CombineAllGrassOnRoot()
    {
        
        
    }

    private Dictionary<string,GameObject> WarmUpPrefab(Dictionary<string,List<Transform>>terrainGrassDic)
    {
        var dic = new Dictionary<string, GameObject>();

        foreach (var i in terrainGrassDic)
        {
            for (int j = 0; j<i.Value.Count; j++)
            {
                if (i.Value[j].childCount <= 0)
                {
                    continue;
                }

                var obj = i.Value[j].GetChild(0).gameObject;

                var prefab = PrefabUtility.GetCorrespondingObjectFromSource(i.Value[0].GetChild(0)).gameObject;
                if(prefab!=null) dic.Add(i.Key, prefab);
                break;
            }
        }


        return dic;
    }
    
    
    GameObject GetNameInArray(GameObject[] objList,string objName)
    {
        foreach (var o in objList)
        {
            if (o.name == objName) return o;
        }

        return null;
    }
    
   

    /// <summary>
    /// 将根节点下的所有草对象根据当前地形的划分重新分批
    /// </summary>
    /// <param name="terrainList"></param>
    /// <param name="root"></param>
    public void SplitTerrain(List<Terrain> terrainList,Transform root) 
    {
        List<Transform> waitToSplit = new List<Transform>();

        foreach (Transform i in root)
        {
            // if(i.name.IndexOf())
            waitToSplit.Add(i); 
        } 
        
        List<Transform> waitToMove = new List<Transform>();
        Bounds cacheBound = new Bounds();
        foreach (var i in terrains)
        {
            cacheBound.center = i.terrainData.bounds.center + i.transform.position;
            cacheBound.size = i.terrainData.bounds.size;
            waitToMove.Clear();
             
            foreach (var obj in waitToSplit)
            {
                if (cacheBound.Contains(obj.position)) waitToMove.Add(obj);       
            }

            if (waitToMove.Count > 0)
            {

                var o = i.transform.Find(root.name);
                if(o==null) o = new GameObject(root.name).transform;
                o.position = Vector3.zero;
                o.parent = i.transform;
                
                
                foreach (var t in waitToMove)
                {
                    t.transform.parent = o.transform;
                    waitToSplit.Remove(t);
                }
            }
            
        } 
        
        
    }
    
    

    public void GetAllTerrain()
    {
        var list = FindObjectsOfType<Terrain>();

        terrains = new List<Terrain>();
        foreach (var i in list)
        {
            terrains.Add(i); 
        }
        Debug.Log(terrains.Count);
        
    }



    public void DrawWaitToBeakBox()
    {
         foreach (var i in waitToBeak)
         {
             if(i==null) continue;
             var terrainData = i.terrainData;
             Handles.color = Color.yellow;
             Handles.DrawWireCube(terrainData.bounds.center+i.transform.position,terrainData.bounds.size);
         }   
    }
    
    public void DrawTerrainsBounds()
    {
        foreach (var i in terrains)
        {
            if(i==null) continue;
            var terrainData = i.terrainData;
            Handles.DrawWireCube(terrainData.bounds.center+i.transform.position,terrainData.bounds.size);
        }
        
    }
    #endregion


    #region 收集管理所有未烘焙草

    
    
    /// <summary>
    /// 用于缓存 每个场景下的所有非烘焙草对象
    /// </summary>
    private class  UnBeakGrassGroup
    {
        public string areaName;
        public List<Transform> _grassObject;
    }

    private void GetAllUnBeakGrass()
    {
        //难道真的只能全场景遍历物体？ 太麻了吧

        int count = EditorSceneManager.sceneCount;

        
        
        for (int sceneID = 0; sceneID < count; sceneID++)
        {
            
           // TODO获取该场景的根节点对象  使用递归查询 如果符合条件便添加
            
        }
        
    }


    /// <summary>
    ///  通过遍历获取 所有子节点 ,返回合适条件的对象
    /// </summary>
    /// <param name="root"></param>
    private void GetGrassOnRoot(Transform root,UnBeakGrassGroup groupData)
    {

        if (root.name.Contains("_group"))
        {
            // TODO所有非烘焙草名称中包含 _group字样 ，所有可以根据名称进行判断该对象是否非烘焙草  
            
        }

        // 条件不通过 便继续递归，直到对象不包含子物体
        foreach (Transform i in root)
        {
           GetGrassOnRoot(i,groupData); 
        } 

    }
    
    
    
     
    
    

    #endregion 
    
    
    #region  VGInstanceRendererDebug

    
    private void DrawDebugData()
    {

        EditorGUILayout.Space(10);

        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
        
        EditorGUILayout.IntField("总Renderer",XYRendering.Vegetation.VGInstancingDataRenererManager.GetInstance().GetRenderCount);
        EditorGUILayout.IntField("总草",XYRendering.Vegetation.VGInstancingDataRenererManager.GetInstance().GetTotlyRenderingNum());
        EditorGUILayout.IntField("草Instance",XYRendering.Vegetation.VGInstancingDataRenererManager.GetInstance().GetFullRenderingNum());
        
        EditorGUILayout.EndVertical();

    }

    #endregion 
    
    
    
    
    #region  基于地形的批量烘焙草


    
    
    
    
    
    private void BeakAllTerrainGrass()
    {
        
    }
    
        
    
    
    
    #endregion
}


}